/*
Copyright (c) [2019年5月1日] [吴超]
[MBT_studio] is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
		 http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
*/
#include "stdafx.h"
#include "S_Px核心.h"

using namespace physx;
using namespace std;


#ifdef _DEBUG 
//#ifdef NDDEBUG 

#pragma comment(lib, "D:/U/DEV/PhysX/Lib/debug/PhysX3DEBUG_x64.lib")
#pragma comment(lib, "D:/U/DEV/PhysX/Lib/debug/PhysX3CharacterKinematicDEBUG_x64.lib")
#pragma comment(lib, "D:/U/DEV/PhysX/Lib/debug/PhysX3CommonDEBUG_x64.lib")
#pragma comment(lib, "D:/U/DEV/PhysX/Lib/debug/PhysX3CookingDEBUG_x64.lib")
#pragma comment(lib, "D:/U/DEV/PhysX/Lib/debug/PhysX3ExtensionsDEBUG.lib")
#pragma comment(lib, "D:/U/DEV/PhysX/Lib/debug/PhysX3VehicleDEBUG.lib")
#pragma comment(lib, "D:/U/DEV/PhysX/Lib/debug/PxFoundationDEBUG_x64.lib")
#pragma comment(lib, "D:/U/DEV/PhysX/Lib/debug/PxFoundationDEBUG_x64.lib")
#pragma comment(lib, "D:/U/DEV/PhysX/Lib/debug/PxPvdSDKDEBUG_x64.lib")


#else

#pragma comment(lib, "D:/U/DEV/PhysX/Lib/release/PhysX3_x64.lib")
#pragma comment(lib, "D:/U/DEV/PhysX/Lib/release/PhysX3CharacterKinematic_x64.lib")
#pragma comment(lib, "D:/U/DEV/PhysX/Lib/release/PhysX3Common_x64.lib")
#pragma comment(lib, "D:/U/DEV/PhysX/Lib/release/PhysX3Cooking_x64.lib")
#pragma comment(lib, "D:/U/DEV/PhysX/Lib/release/PhysX3Extensions.lib")
#pragma comment(lib, "D:/U/DEV/PhysX/Lib/release/PhysX3Vehicle.lib")
#pragma comment(lib, "D:/U/DEV/PhysX/Lib/release/PsFastXml_x64.lib")
#pragma comment(lib, "D:/U/DEV/PhysX/Lib/release/PxFoundation_x64.lib")
#pragma comment(lib, "D:/U/DEV/PhysX/Lib/release/PxTask_x64.lib")


#endif






//static PxDefaultErrorCallback	gDefaultErrorCallback;
//static PxDefaultAllocator		gDefaultAllocatorCallback;

static PxPvd*					gPvd = 0;

struct PvdParameters
{
	string							ip;
	PxU32							port;
	PxU32							timeout;
	bool							useFullPvdConnection;

	PvdParameters()
		: port(5425)
		, timeout(10)
		, useFullPvdConnection(true)
	{
		ip = "127.0.0.1";
	}
};
static PvdParameters			gPvdParams;


class SampleGpuLoadHook : public PxGpuLoadHook
{
	virtual const char* getPhysXGpuDllName() const
	{
		return "D:/U/Project/x64/BlenderSandbox/Release/PhysX3Gpu_x64.dll";
	}
	virtual const char* getPhysXGpuDEBUGDllName() const
	{
		return "D:/U/Project/x64/BlenderSandbox/Release/PhysX3GpuDEBUG_x64.dll";
	}
	virtual const char* getPhysXGpuCHECKEDDllName() const
	{
		return "D:/U/Project/x64/BlenderSandbox/Release/PhysX3GpuCHECKED_x64.dll";
	}
	virtual const char* getPhysXGpuPROFILEDllName() const
	{
		return "D:/U/Project/x64/BlenderSandbox/Release/PhysX3GpuPROFILE_x64.dll";
	}
	
} gGpuLoadHook;


/*class SampleDelayLoadHook : public PxDelayLoadHook
{
	virtual const char* getPhysXCommonDEBUGDllName() const {
		return "PhysX3CommonDEBUG_x64.dll";
	}
	virtual const char* getPhysXCommonCHECKEDDllName() const {
		return "PhysX3CommonCHECKED_x64.dll";
	}
	virtual const char* getPhysXCommonPROFILEDllName() const {
		return "PhysX3CommonPROFILE_x64.dll";
	}
	virtual const char* getPhysXCommonDllName() const {
		return "PhysX3Common_x64.dll";
	}
	virtual const char* getPxFoundationDEBUGDllName() const {
		return "PxFoundationDEBUG_x64.dll";
	}
	virtual const char* getPxFoundationCHECKEDDllName() const {
		return "PxFoundationCHECKED_x64.dll";
	}
	virtual const char* getPxFoundationPROFILEDllName() const {
		return "PxFoundationPROFILE_x64.dll";
	}
	virtual const char* getPxFoundationDllName() const {
		return "PxFoundation_x64.dll";
	}
	virtual const char* getPxPvdSDKDEBUGDllName() const {
		return "PxPvdSDKDEBUG_x64.dll";
	}
	virtual const char* getPxPvdSDKCHECKEDDllName() const {
		return "PxPvdSDKCHECKED_x64.dll";
	}
	virtual const char* getPxPvdSDKPROFILEDllName() const {
		return "PxPvdSDKPROFILE_x64.dll";
	}
	virtual const char* getPxPvdSDKDllName() const {
		return "PxPvdSDK_x64.dll";
	}
} gDelayLoadHook;*/




S_Px物理引擎核心::S_Px物理引擎核心() :
	m_CPU调度(0)
{
	m_Foundation = PxCreateFoundation(PX_FOUNDATION_VERSION, m_DefaultAllocatorCallback, m_DefaultErrorCallback);
	mSerializationRegistry = 0;

	
	m_CudaContextManager = 0;
	PxSetPhysXGpuLoadHook(&gGpuLoadHook);
	PxCudaContextManagerDesc cudaContextManagerDesc;
	m_CudaContextManager = PxCreateCudaContextManager(*m_Foundation, cudaContextManagerDesc);
	if (m_CudaContextManager) {
		if (!m_CudaContextManager->contextIsValid()){
			m_CudaContextManager->release();
			m_CudaContextManager = NULL;
		}
	}





#ifdef _DEBUG
	gPvd = physx::PxCreatePvd(*m_Foundation);
	gPvdParams.timeout = 100000;
	PxPvdTransport* mTransport = physx::PxDefaultPvdSocketTransportCreate(gPvdParams.ip.c_str(), gPvdParams.port, gPvdParams.timeout);
	
#endif



	PxTolerancesScale scale = physx::PxTolerancesScale();
	//customizeTolerances(scale);

	PxCookingParams params(scale);
	params.meshWeldTolerance = 0.001f;
	params.meshPreprocessParams = PxMeshPreprocessingFlags(PxMeshPreprocessingFlag::eWELD_VERTICES);
	params.buildGPUData = true; //Enable GRB data being produced in cooking.

	m_Physics = PxCreatePhysics(PX_PHYSICS_VERSION, *m_Foundation, physx::PxTolerancesScale(), true, gPvd);
	m_Cooking = PxCreateCooking(PX_PHYSICS_VERSION, *m_Foundation, params);
	


	bool 链接成功 = false;
#ifdef _DEBUG
	if (gPvd) {
		PxInitExtensions(*m_Physics, gPvd);
		/*PxPvdInstrumentationFlags mPvdFlags = physx::PxPvdInstrumentationFlag::eALL;
		if (!gPvdParams.useFullPvdConnection) {
			mPvdFlags = physx::PxPvdInstrumentationFlag::ePROFILE;
		}
		gPvd->connect(*mTransport, mPvdFlags);*/
		physx::PxPvdTransport* mTransport = physx::PxDefaultPvdFileTransportCreate("D:/Temp/sample.pxd2");
		if (mTransport == NULL)  return;
		PxPvdInstrumentationFlags mPvdFlags = physx::PxPvdInstrumentationFlag::eALL;
		

		链接成功 = gPvd->connect(*mTransport, mPvdFlags);
		链接成功;

	}
#endif


	//PxInitExtensions(*m_Physics, 0);

	bool 车辆初始化 = false;
	车辆初始化 = PxInitVehicleSDK(*m_Physics, mSerializationRegistry);
	PxVehicleSetBasisVectors(PxVec3(0, 1, 0), PxVec3(0, 0, 1));
	PxVehicleSetUpdateMode(PxVehicleUpdateMode::eVELOCITY_CHANGE);
	PxVehicleSetSweepHitRejectionAngles(M_PI / 2, M_PI / 4);
	//PxVehicleSetMaxHitActorAcceleration()
}

S_Px物理引擎核心::~S_Px物理引擎核心() {
	//PxCloseVehicleSDK();
	//gPvd->disconnect();
	//PxCloseVehicleSDK(mSerializationRegistry);

}



physx::PxScene* S_Px物理引擎核心::f_scene_创建场景() {
	physx::PxScene* scene = 0;

	physx::PxSceneDesc scene描述(m_Physics->getTolerancesScale());
	scene描述.gravity = physx::PxVec3(0.0f, -9.8f, 0.0f);
	scene描述.filterShader = physx::PxDefaultSimulationFilterShader;
	

	m_CPU调度 = PxDefaultCpuDispatcherCreate(48);
	scene描述.cpuDispatcher = m_CPU调度;

	if (m_CudaContextManager) {
		scene描述.gpuDispatcher = m_CudaContextManager->getGpuDispatcher();
		scene描述.broadPhaseType = PxBroadPhaseType::eGPU;
		scene描述.flags |= PxSceneFlag::eENABLE_GPU_DYNAMICS;
		//sceneDesc.flags |= PxSceneFlag::eENABLE_AVERAGE_POINT;
		//sceneDesc.flags |= PxSceneFlag::eADAPTIVE_FORCE;
		scene描述.sceneQueryUpdateMode = PxSceneQueryUpdateMode::eBUILD_ENABLED_COMMIT_DISABLED;
		//sceneDesc.flags |= PxSceneFlag::eDISABLE_CONTACT_CACHE;
		scene描述.broadPhaseType = PxBroadPhaseType::eGPU;

		//scene描述.gpuDynamicsConfig.patchStreamSize = 2048 * 1024;
		//scene描述.gpuDynamicsConfig.tempBufferCapacity = (64 * 1024 * 1024);
		//scene描述.gpuDynamicsConfig.constraintBufferCapacity = (64 * 1024 * 1024);
		uint32 倍数 = 1;
		scene描述.gpuDynamicsConfig.constraintBufferCapacity = (32 * 倍数 * 2048 * 2048);
		scene描述.gpuDynamicsConfig.contactBufferCapacity = (24* 倍数 * 2048 * 2048);
		scene描述.gpuDynamicsConfig.tempBufferCapacity = (16* 倍数 * 2048 * 2048);
		scene描述.gpuDynamicsConfig.contactStreamSize = (2048 * 512* 倍数);
		scene描述.gpuDynamicsConfig.patchStreamSize = (2048 * 128* 倍数);
		scene描述.gpuDynamicsConfig.forceStreamCapacity = (倍数 * 1024 * 1024);
		scene描述.gpuDynamicsConfig.heapCapacity = (64* 倍数 * 1024 * 1024);
		scene描述.gpuDynamicsConfig.foundLostPairsCapacity = (256* 倍数 * 1024);
	}
	else {
		
	}

	
	scene描述.flags |= PxSceneFlag::eENABLE_PCM;
	scene描述.flags |= PxSceneFlag::eENABLE_STABILIZATION;
	//scene描述.flags |= PxPairFlag::eSOLVE_CONTACT;
	

	scene = m_Physics->createScene(scene描述);

	scene->setFlag(PxSceneFlag::eENABLE_ACTIVE_ACTORS, true);
	scene->setFlag(PxSceneFlag::eENABLE_ACTIVETRANSFORMS, true);

	scene->setGravity({ 0.0, -9.8, 0.0 });



	

	PxSceneFlags flag = scene->getFlags();
	PX_UNUSED(flag);
	//scene->setVisualizationParameter(PxVisualizationParameter::eSCALE, mInitialDebugRender ? mDebugRenderScale : 0.0f);
	scene->setVisualizationParameter(PxVisualizationParameter::eCOLLISION_SHAPES, 1.0f);



#ifdef _DEBUG
	PxPvdSceneClient* pvdClient = scene->getScenePvdClient(); 
	if (pvdClient) { 
		pvdClient->setScenePvdFlag(PxPvdSceneFlag::eTRANSMIT_CONSTRAINTS, true);  
		pvdClient->setScenePvdFlag(PxPvdSceneFlag::eTRANSMIT_CONTACTS, true);  
		pvdClient->setScenePvdFlag(PxPvdSceneFlag::eTRANSMIT_SCENEQUERIES, true); 
	}
#endif

	return scene;

}

